/*
 * Copyright 2009 Armando Blancas
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package tests.taskgraph.tasks.data;

import java.io.IOException;

import junit.framework.Assert;
import junit.framework.JUnit4TestAdapter;

import org.junit.Test;

import taskgraph.channels.BooleanChannel;
import taskgraph.channels.ByteChannel;
import taskgraph.channels.Channel;
import taskgraph.channels.DoubleChannel;
import taskgraph.channels.FloatChannel;
import taskgraph.channels.IntChannel;
import taskgraph.channels.LongChannel;
import taskgraph.channels.ShortChannel;
import taskgraph.ports.BooleanInputPort;
import taskgraph.ports.ByteInputPort;
import taskgraph.ports.DoubleInputPort;
import taskgraph.ports.FloatInputPort;
import taskgraph.ports.InputPort;
import taskgraph.ports.IntInputPort;
import taskgraph.ports.LongInputPort;
import taskgraph.ports.OutputPort;
import taskgraph.ports.ShortInputPort;
import taskgraph.tasks.data.ReadNativeArray;

public class ReadNativeArrayTest {

	/**
	 * Runs the test suite in this class from the command line.
	 * 
	 * @param args	Arguments are ignored.
	 */
	public static void main(String[] args) {
		org.junit.runner.JUnitCore.runClasses(ReadNativeArrayTest.class);
	}
	
	/**
	 * Provides compatibility with 3.x versions of JUnit.
	 * 
	 * @return A 3.x-compatible test suite.
	 */
	public static junit.framework.Test suite() {
		return new JUnit4TestAdapter(ReadNativeArrayTest.class);
	}
	
	/*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Test the constructors.                                               | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/
	
	@Test
	public void defaultConstructor() {
		ReadNativeArray task = new ReadNativeArray();
		Assert.assertNotNull(task);
	}
	
	@Test
	public void defaultInstanceClass() {
		ReadNativeArray task = new ReadNativeArray();
		Assert.assertEquals(ReadNativeArray.class, task.getClass());
	}

	@Test
	public void constructorWithPort() {
		Channel<Object> channel = new Channel<Object>();
		OutputPort<Object> output = channel.getOutputPort();
		ReadNativeArray task = new ReadNativeArray(output);
		Assert.assertNotNull(task);
	}
	
	@Test
	public void constructorWithPortAndClass() {
		Channel<Object> channel = new Channel<Object>();
		OutputPort<Object> output = channel.getOutputPort();
		ReadNativeArray task = new ReadNativeArray(output);
		Assert.assertEquals(ReadNativeArray.class, task.getClass());
	}

    /*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Test the run method.                                                 | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/
	
	@Test
	public void testRunBoolean() throws IOException {
		boolean[] data = { false, true, true, false, true, false, false, true };

		BooleanChannel channel = new BooleanChannel();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort(), data);
		task.run();

		BooleanInputPort port = channel.getInputPort();
		for (boolean expected : data)
			Assert.assertEquals(expected, port.read());
		port.close();
	}

	@Test
	public void testRunBooleanWrapper() throws IOException {
		boolean[] data = { false, true, true, false, true, false, false, true };

		Channel<Object> channel = new Channel<Object>();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort());
		task.setBooleanArray(data);
		task.run();

		InputPort<Object> port = channel.getInputPort();
		for (boolean expected : data) {
			boolean value = (Boolean) port.read();
			Assert.assertEquals(expected, value);
		}
		port.close();
	}

	@Test
	public void testRunByte() throws IOException {
		byte[] data = { 2, 4, 8, 16, 32, 64, 127, 64, 32, 16, 8, 4, 2 };

		ByteChannel channel = new ByteChannel();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort(), data);
		task.run();

		ByteInputPort port = channel.getInputPort();
		for (byte expected : data)
			Assert.assertEquals(expected, port.read());
		port.close();
	}

	@Test
	public void testRunByteWrapper() throws IOException {
		byte[] data = { 2, 4, 8, 16, 32, 64, 127, 64, 32, 16, 8, 4, 2 };

		Channel<Object> channel = new Channel<Object>();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort());
		task.setByteArray(data);
		task.run();

		InputPort<Object> port = channel.getInputPort();
		for (byte expected : data) {
			byte value = (Byte) port.read();
			Assert.assertEquals(expected, value);
		}
		port.close();
	}

	@Test
	public void testRunShort() throws IOException {
		short[] data = { 102, 2004, 8500, 1667, 3221, 2112, 5005, 999, 666 };

		ShortChannel channel = new ShortChannel();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort(), data);
		task.run();

		ShortInputPort port = channel.getInputPort();
		for (short expected : data)
			Assert.assertEquals(expected, port.read());
		port.close();
	}

	@Test
	public void testRunShortWrapper() throws IOException {
		short[] data = { 102, 2004, 8500, 1667, 3221, 2112, 5005, 999, 666 };

		Channel<Object> channel = new Channel<Object>();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort());
		task.setShortArray(data);
		task.run();

		InputPort<Object> port = channel.getInputPort();
		for (short expected : data) {
			short value = (Short) port.read();
			Assert.assertEquals(expected, value);
		}
		port.close();
	}

	@Test
	public void testRunInt() throws IOException {
		int[] data = { 102700, 2004212, 12228500, 166700, 121, 99999, 666000 };

		IntChannel channel = new IntChannel();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort(), data);
		task.run();

		IntInputPort port = channel.getInputPort();
		for (int expected : data)
			Assert.assertEquals(expected, port.read());
		port.close();
	}

	@Test
	public void testRunIntWrapper() throws IOException {
		int[] data = { 102700, 2004212, 12228500, 166700, 121, 99999, 666000 };

		Channel<Object> channel = new Channel<Object>();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort());
		task.setIntArray(data);
		task.run();

		InputPort<Object> port = channel.getInputPort();
		for (int expected : data) {
			int value = (Integer) port.read();
			Assert.assertEquals(expected, value);
		}
		port.close();
	}

	@Test
	public void testRunLong() throws IOException {
		long[] data = { 1027005656540L, 200421210000L, 12228500400L, 16670000L};

		LongChannel channel = new LongChannel();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort(), data);
		task.run();

		LongInputPort port = channel.getInputPort();
		for (long expected : data)
			Assert.assertEquals(expected, port.read());
		port.close();
	}

	@Test
	public void testRunLongWrapper() throws IOException {
		long[] data = { 1027005656540L, 200421210000L, 12228500400L, 16670000L};

		Channel<Object> channel = new Channel<Object>();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort());
		task.setLongArray(data);
		task.run();

		InputPort<Object> port = channel.getInputPort();
		for (long expected : data) {
			long value = (Long) port.read();
			Assert.assertEquals(expected, value);
		}
		port.close();
	}

	@Test
	public void testRunFloat() throws IOException {
		float[] data = { 102700.56540F, 200.1210000F, 1222.850040F, 1.6670000F};

		FloatChannel channel = new FloatChannel();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort(), data);
		task.run();

		FloatInputPort port = channel.getInputPort();
		for (float expected : data)
			Assert.assertEquals(expected, port.read());
		port.close();
	}

	@Test
	public void testRunFloatWrapper() throws IOException {
		float[] data = { 102700.56540F, 200.1210000F, 1222.850040F, 1.6670000F};

		Channel<Object> channel = new Channel<Object>();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort());
		task.setFloatArray(data);
		task.run();

		InputPort<Object> port = channel.getInputPort();
		for (float expected : data) {
			float value = (Float) port.read();
			Assert.assertEquals(expected, value);
		}
		port.close();
	}

	@Test
	public void testRunDouble() throws IOException {
		double[] data = { 102700.56540, 200.12100009, 1222.850040, 1.667000011};

		DoubleChannel channel = new DoubleChannel();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort(), data);
		task.run();

		DoubleInputPort port = channel.getInputPort();
		for (double expected : data)
			Assert.assertEquals(expected, port.read());
		port.close();
	}

	@Test
	public void testRunDoubleWrapper() throws IOException {
		double[] data = { 102700.56540, 200.12100009, 1222.850040, 1.667000011};

		Channel<Object> channel = new Channel<Object>();
		ReadNativeArray task = new ReadNativeArray(channel.getOutputPort());
		task.setDoubleArray(data);
		task.run();

		InputPort<Object> port = channel.getInputPort();
		for (double expected : data) {
			double value = (Double) port.read();
			Assert.assertEquals(expected, value);
		}
		port.close();
	}

    /*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Negative tests for constructors.                                     | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/

	@Test(expected=IllegalArgumentException.class)
	public void constructorWithNullOutputPort() throws IOException {
		new ReadNativeArray(null);
	}

    /*+----------------------------------------------------------------------+
	  |                                                                      | 
	  | Negative tests.                                                      | 
	  |                                                                      | 
	  +----------------------------------------------------------------------+*/

}
